package com.onesports.intelligent.k12.polarlight.security.wx;

import com.onesports.intelligent.k12.polarlight.constant.BizConstants;
import com.onesports.intelligent.k12.polarlight.domain.entity.organization.Coach;
import com.onesports.intelligent.k12.polarlight.domain.entity.sys.WxUser;
import com.onesports.intelligent.k12.polarlight.security.DomainUserDetails;
import com.onesports.intelligent.k12.polarlight.security.UserAlreadyUsedException;
import com.onesports.intelligent.k12.polarlight.service.coach.CoachService;
import com.onesports.intelligent.k12.polarlight.service.student.WxUserService;
import com.onesports.intelligent.k12.polarlight.service.wx.WxUserPurseService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;


/**
 * @author aj
 */
public class WxAuthenticationProvider implements AuthenticationProvider {

    @Resource
    private WxUserService wxUserService;
    @Resource
    private WxUserPurseService wxUserPurseService;
    @Resource
    private CoachService coachService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        WxAuthenticationToken authenticationToken = (WxAuthenticationToken) authentication;
        WxLoginInfo wxLoginInfo = (WxLoginInfo) authentication.getDetails();
        String openId = (String) authenticationToken.getPrincipal();

        return getWxUser(wxLoginInfo, openId);
    }


    private Authentication getWxUser(WxLoginInfo wxLoginInfo, String openId) {
        String phone = wxLoginInfo.getPurePhoneNumber();
        List<WxUser> users = wxUserService.getByPhoneOrOpenId(phone, openId);
        WxUser user;
        boolean isCoach = false;
        String coachId = "";
        if (CollectionUtils.isEmpty(users)) {
            user = new WxUser();
            user.setOpenId(openId);
            user.setPhone(phone);
            user.setIsCoach(false);
            if (wxUserService.save(user)) {
                //添加钱包
                wxUserPurseService.addUserPurseByWxUserId(user.getId());
            }
        } else if (users.size() > 1) {
            throw new UserAlreadyUsedException("该手机号已绑定其他微信");
        } else
        // 有一条记录
        {
            user = users.get(0);
            boolean isBinding = phone.equals(user.getPhone()) &&
                    (StringUtils.isEmpty(user.getOpenId())
                            || openId.equals(user.getOpenId()));
            if (isBinding) {
                user.setOpenId(openId);
                wxUserService.updateById(user);
            } else {
                throw new UserAlreadyUsedException("当前微信已绑定其他手机号");
            }
            //切换成教练
            Coach coach = coachService.getByWxUserId(user.getId());
            if (coach != null && coach.getStatus()) {
                isCoach = true;
                coachId = coach.getId();
            }
        }

        List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
        if (isCoach) {
            grantedAuthorities.add(new SimpleGrantedAuthority(BizConstants.ROLE_MINI_APP_COACH));
        } else {
            grantedAuthorities.add(new SimpleGrantedAuthority(BizConstants.ROLE_MINI_APP));
        }
        DomainUserDetails userDetails = DomainUserDetails.builder().username(phone)
                .current(user.getId())
                .coachId(coachId)
                .phone(phone)
                .avatar(user.getAvatar())
                .nickname(user.getNickname())
                .coach(isCoach)
                .authorities(grantedAuthorities)
                .build();
        WxAuthenticationToken result = new WxAuthenticationToken(userDetails, grantedAuthorities);
        return result;
    }


    @Override
    public boolean supports(Class<?> authentication) {
        return WxAuthenticationToken.class.isAssignableFrom(authentication);
    }

}
